
/* Dissection of a single byte array. Holds tvbuff info as
 * well as proto_tree info. As long as the epan_dissect_t for a byte
 * array is in existence, you must not free or move that byte array,
 * as the structures that the epan_dissect_t contains might have pointers
 * to addresses in your byte array.
 */
struct epan_dissect {
	struct epan_session *session;
	tvbuff_t	*tvb;
	proto_tree	*tree;
	packet_info	pi;
};

struct epan_session {
	struct packet_provider_data *prov;	/* packet provider data for this session */
	struct packet_provider_funcs funcs;	/* functions using that data */
};
typedef struct epan_session epan_t;



typedef struct _frame_data {
  uint32_t     num;          /**< Frame number */
  uint32_t     pkt_len;      /**< Packet length */
  uint32_t     cap_len;      /**< Amount actually captured */
  uint32_t     cum_bytes;    /**< Cumulative bytes into the capture */
  int64_t      file_off;     /**< File offset */
  /* These two are pointers, meaning 64-bit on LP64 (64-bit UN*X) and
     LLP64 (64-bit Windows) platforms.  Put them here, one after the
     other, so they don't require padding between them. */
  GSList      *pfd;          /**< Per frame proto data */
  GHashTable  *dependent_frames;     /**< A hash table of frames which this one depends on */
  const struct _color_filter *color_filter;  /**< Per-packet matching color_filter_t object */
  uint8_t      tcp_snd_manual_analysis;   /**< TCP SEQ Analysis Overriding, 0 = none, 1 = OOO, 2 = RET , 3 = Fast RET, 4 = Spurious RET  */
  /* Keep the bitfields below to 24 bits, so this plus the previous field
     are 32 bits. (XXX - The previous field could be a bitfield too.) */
  unsigned int passed_dfilter   : 1; /**< 1 = display, 0 = no display */
  unsigned int dependent_of_displayed : 1; /**< 1 if a displayed frame depends on this frame */
  /* Do NOT use packet_char_enc enum here: MSVC compiler does not handle an enum in a bit field properly */
  unsigned int encoding         : 1; /**< Character encoding (ASCII, EBCDIC...) */
  unsigned int visited          : 1; /**< Has this packet been visited yet? 1=Yes,0=No*/
  unsigned int marked           : 1; /**< 1 = marked by user, 0 = normal */
  unsigned int ref_time         : 1; /**< 1 = marked as a reference time frame, 0 = normal */
  unsigned int ignored          : 1; /**< 1 = ignore this frame, 0 = normal */
  unsigned int has_ts           : 1; /**< 1 = has time stamp, 0 = no time stamp */
  unsigned int has_modified_block : 1; /** 1 = block for this packet has been modified */
  unsigned int need_colorize    : 1; /**< 1 = need to (re-)calculate packet color */
  unsigned int tsprec           : 4; /**< Time stamp precision -2^tsprec gives up to femtoseconds */
  nstime_t     abs_ts;       /**< Absolute timestamp */
  nstime_t     shift_offset; /**< How much the abs_tm of the frame is shifted */
  uint32_t     frame_ref_num; /**< Previous reference frame (0 if this is one) */
  uint32_t     prev_dis_num; /**< Previous displayed frame (0 if first one) */
} frame_data;

struct tvbuff {
	/* Doubly linked list pointers */
	tvbuff_t                *next;

	/* Record-keeping */
	const struct tvb_ops   *ops;
	bool		initialized;
	unsigned			flags;
	struct tvbuff		*ds_tvb;  /**< data source top-level tvbuff */

	/** Pointer to the data for this tvbuff.
	 * It might be null, which either means that 1) it's a
	 * zero-length tvbuff or 2) the tvbuff was lazily
	 * constructed, so that we don't allocate a buffer of
	 * backing data and fill it in unless we need that
	 * data, e.g. when tvb_get_ptr() is called.
	 */
	const uint8_t		*real_data;

	/** Amount of data that's available from the capture
	 * file.  This is the length of virtual buffer (and/or
	 * real_data).  It may be less than the reported
	 * length if this is from a packet that was cut short
	 * by the capture process.
	 *
	 * This must never be > reported_length or contained_length. */
	unsigned			length;

	/** Amount of data that was reported as being in
	 * the packet or other data that this represents.
	 * As indicated above, it may be greater than the
	 * amount of data that's available. */
	unsigned			reported_length;

	/** If this was extracted from a parent tvbuff,
	 * this is the amount of extracted data that
	 * was reported as being in the parent tvbuff;
	 * if this represents a blob of data in that
	 * tvbuff that has a length specified by data
	 * in that tvbuff, it might be greater than
	 * the amount of data that was actually there
	 * to extract, so it could be greater than
	 * reported_length.
	 *
	 * If this wasn't extracted from a parent tvbuff,
	 * this is the same as reported_length.
	 *
	 * This must never be > reported_length. */
	unsigned			contained_length;

	/* Offset from beginning of first "real" tvbuff. */
	int			raw_offset;
};
typedef struct tvbuff tvbuff_t;

struct _fvalue_t {
	const ftype_t	*ftype;
	union {
		/* Put a few basic types in here */
		uint64_t		uinteger64;
		int64_t			sinteger64;
		double			floating;
		wmem_strbuf_t		*strbuf;
		GBytes			*bytes;
		ipv4_addr_and_mask	ipv4;
		ipv6_addr_and_prefix	ipv6;
		e_guid_t		guid;
		nstime_t		time;
		protocol_value_t 	protocol;
		uint16_t		sfloat_ieee_11073;
		uint32_t		float_ieee_11073;
	} value;
};
typedef struct _fvalue_t fvalue_t;

typedef struct _packet_info {
  const char *current_proto;        /**< name of protocol currently being dissected */
  struct epan_column_info *cinfo;   /**< Column formatting information */
  uint32_t presence_flags;           /**< Presence flags for some items */
  uint32_t num;                      /**< Frame number */
  nstime_t abs_ts;                  /**< Packet absolute time stamp */
  nstime_t rel_ts;                  /**< Relative timestamp (yes, it can be negative) */
  nstime_t rel_cap_ts;              /**< Relative timestamp from capture start (might be negative for broken files) */
  bool rel_cap_ts_present;      /**< Relative timestamp from capture start valid */
  frame_data *fd;
  union wtap_pseudo_header *pseudo_header;
  wtap_rec *rec;                    /**< Record metadata */
  GSList *data_src;                 /**< Frame data sources */
  address dl_src;                   /**< link-layer source address */
  address dl_dst;                   /**< link-layer destination address */
  address net_src;                  /**< network-layer source address */
  address net_dst;                  /**< network-layer destination address */
  address src;                      /**< source address (net if present, DL otherwise )*/
  address dst;                      /**< destination address (net if present, DL otherwise )*/
  uint32_t vlan_id;                  /**< First encountered VLAN Id if present otherwise 0 */
  const char *noreassembly_reason;  /**< reason why reassembly wasn't done, if any */
  bool fragmented;              /**< true if the protocol is only a fragment */
  struct {
    uint32_t in_error_pkt:1;         /**< true if we're inside an {ICMP,CLNP,...} error packet */
    uint32_t in_gre_pkt:1;           /**< true if we're encapsulated inside a GRE packet */
  } flags;
  port_type ptype;                  /**< type of the following two port numbers */
  uint32_t srcport;                  /**< source port */
  uint32_t destport;                 /**< destination port */
  uint32_t match_uint;               /**< matched uint for calling subdissector from table */
  const char *match_string;         /**< matched string for calling subdissector from table */
  bool use_conv_addr_port_endpoints; /**< true if address/port endpoints member should be used for conversations */
  struct conversation_addr_port_endpoints* conv_addr_port_endpoints; /**< Data that can be used for address+port conversations, including wildcarding */
  struct conversation_element *conv_elements; /**< Arbitrary conversation identifier; can't be wildcarded */
  uint16_t can_desegment;            /**< >0 if this segment could be desegmented.
                                         A dissector that can offer this API (e.g.
                                         TCP) sets can_desegment=2, then
                                         can_desegment is decremented by 1 each time
                                         we pass to the next subdissector. Thus only
                                         the dissector immediately above the
                                         protocol which sets the flag can use it*/
  uint16_t saved_can_desegment;      /**< Value of can_desegment before current
                                         dissector was called.  Supplied so that
                                         dissectors for proxy protocols such as
                                         SOCKS can restore it, allowing the
                                         dissectors that they call to use the
                                         TCP dissector's desegmentation (SOCKS
                                         just retransmits TCP segments once it's
                                         finished setting things up, so the TCP
                                         desegmentor can desegment its payload). */
  int desegment_offset;             /**< offset to stuff needing desegmentation */
#define DESEGMENT_ONE_MORE_SEGMENT 0x0fffffff
#define DESEGMENT_UNTIL_FIN        0x0ffffffe
  uint32_t desegment_len;            /**< requested desegmentation additional length
                                       or
                                       DESEGMENT_ONE_MORE_SEGMENT:
                                         Desegment one more full segment
                                         (warning! only partially implemented)
                                       DESEGMENT_UNTIL_FIN:
                                         Desegment all data for this tcp session
                                         until the FIN segment.
                                    */
  uint16_t want_pdu_tracking;    /**< >0 if the subdissector has specified
                                   a value in 'bytes_until_next_pdu'.
                                   When a dissector detects that the next PDU
                                   will start beyond the start of the next
                                   segment, it can set this value to 2
                                   and 'bytes_until_next_pdu' to the number of
                                   bytes beyond the next segment where the
                                   next PDU starts.

                                   If the protocol dissector below this
                                   one is capable of PDU tracking it can
                                   use this hint to detect PDUs that starts
                                   unaligned to the segment boundaries.
                                   The TCP dissector is using this hint from
                                   (some) protocols to detect when a new PDU
                                   starts in the middle of a tcp segment.

                                   There is intelligence in the glue between
                                   dissector layers to make sure that this
                                   request is only passed down to the protocol
                                   immediately below the current one and not
                                   any further.
                                */
  uint32_t bytes_until_next_pdu;

  int     p2p_dir;              /**< Packet was captured as an
                                       outbound (P2P_DIR_SENT)
                                       inbound (P2P_DIR_RECV)
                                       unknown (P2P_DIR_UNKNOWN) */

  GHashTable *private_table;    /**< a hash table passed from one dissector to another */

  wmem_list_t *layers;          /**< layers of each protocol */
  wmem_map_t *proto_layers;     /** map of proto_id to curr_proto_layer_num. */
  uint8_t curr_layer_num;        /**< The current "depth" or layer number in the current frame */
  uint8_t curr_proto_layer_num;  /**< The current "depth" or layer number for this dissector in the current frame */
  uint16_t link_number;

  uint16_t clnp_srcref;          /**< clnp/cotp source reference (can't use srcport, this would confuse tpkt) */
  uint16_t clnp_dstref;          /**< clnp/cotp destination reference (can't use dstport, this would confuse tpkt) */

  int link_dir;                 /**< 3GPP messages are sometime different UP link(UL) or Downlink(DL) */

  int16_t src_win_scale;        /**< Rcv.Wind.Shift src applies when sending segments; -1 unknown; -2 disabled */
  int16_t dst_win_scale;        /**< Rcv.Wind.Shift dst applies when sending segments; -1 unknown; -2 disabled */

  GSList* proto_data;          /**< Per packet proto data */

  GSList* frame_end_routines;

  wmem_allocator_t *pool;      /**< Memory pool scoped to the pinfo struct */
  struct epan_session *epan;
  const char *heur_list_name;    /**< name of heur list if this packet is being heuristically dissected */
  int dissection_depth;         /**< The current "depth" or layer number in the current frame */

  uint32_t stream_id;            /**< Conversation Stream ID of the highest protocol */
} packet_info;

enum ftenum {
	FT_NONE,	/* used for text labels with no value */
	FT_PROTOCOL,
	FT_BOOLEAN,	/* true and false come from <glib.h> */
	FT_CHAR,	/* 1-octet character as 0-255 */
	FT_UINT8,
	FT_UINT16,
	FT_UINT24,	/* really a UINT32, but displayed as 6 hex-digits if FD_HEX*/
	FT_UINT32,
	FT_UINT40,	/* really a UINT64, but displayed as 10 hex-digits if FD_HEX*/
	FT_UINT48,	/* really a UINT64, but displayed as 12 hex-digits if FD_HEX*/
	FT_UINT56,	/* really a UINT64, but displayed as 14 hex-digits if FD_HEX*/
	FT_UINT64,
	FT_INT8,
	FT_INT16,
	FT_INT24,	/* same as for UINT24 */
	FT_INT32,
	FT_INT40, /* same as for UINT40 */
	FT_INT48, /* same as for UINT48 */
	FT_INT56, /* same as for UINT56 */
	FT_INT64,
	FT_IEEE_11073_SFLOAT,
	FT_IEEE_11073_FLOAT,
	FT_FLOAT,
	FT_DOUBLE,
	FT_ABSOLUTE_TIME,
	FT_RELATIVE_TIME,
	FT_STRING,	/* counted string, with no null terminator */
	FT_STRINGZ,	/* null-terminated string */
	FT_UINT_STRING,	/* counted string, with count being the first part of the value */
	FT_ETHER,
	FT_BYTES,
	FT_UINT_BYTES,
	FT_IPv4,
	FT_IPv6,
	FT_IPXNET,
	FT_FRAMENUM,	/* a UINT32, but if selected lets you go to frame with that number */
	FT_GUID,	/* GUID, UUID */
	FT_OID,		/* OBJECT IDENTIFIER */
	FT_EUI64,
	FT_AX25,
	FT_VINES,
	FT_REL_OID,	/* RELATIVE-OID */
	FT_SYSTEM_ID,
	FT_STRINGZPAD,	/* null-padded string */
	FT_FCWWN,
	FT_STRINGZTRUNC,	/* null-truncated string */
	FT_NUM_TYPES, /* last item number plus one */
	FT_SCALAR,		/* Pseudo-type used only internally for certain
				 * arithmetic operations. */
};

typedef enum {
    HF_REF_TYPE_NONE,       /**< Field is not referenced */
    HF_REF_TYPE_INDIRECT,   /**< Field is indirectly referenced (only applicable for FT_PROTOCOL) via. its child */
    HF_REF_TYPE_DIRECT,     /**< Field is directly referenced */
    HF_REF_TYPE_PRINT       /**< Field is directly referenced for printing (so don't fake its representation either) */
} hf_ref_type;

/** information describing a header field */
typedef struct _header_field_info header_field_info;

/** information describing a header field */
struct _header_field_info {
    /* ---------- set by dissector --------- */
    const char        *name;              /**< [FIELDNAME] full name of this field */
    const char        *abbrev;            /**< [FIELDFILTERNAME] filter name of this field */
    enum ftenum        type;              /**< [FIELDTYPE] field type, one of FT_ (from ftypes.h) */
    int                display;           /**< [FIELDDISPLAY] one of BASE_, or field bit-width if FT_BOOLEAN and non-zero bitmask */
    const void        *strings;           /**< [FIELDCONVERT] value_string, val64_string, range_string or true_false_string,
                                               typically converted by VALS(), RVALS() or TFS().
                                               If this is an FT_PROTOCOL or BASE_PROTOCOL_INFO then it points to the
                                               associated protocol_t structure */
    uint64_t           bitmask;           /**< [BITMASK] bitmask of interesting bits */
    const char        *blurb;             /**< [FIELDDESCR] Brief description of field */

    /* ------- set by proto routines (prefilled by HFILL macro, see below) ------ */
    int                id;                /**< Field ID */
    int                parent;            /**< parent protocol tree */
    hf_ref_type        ref_type;          /**< is this field referenced by a filter */
    int                same_name_prev_id; /**< ID of previous hfinfo with same abbrev */
    header_field_info *same_name_next;    /**< Link to next hfinfo with same abbrev */
};

/** Used when registering many fields at once, using proto_register_field_array() */
typedef struct hf_register_info {
    int               *p_id;   /**< written to by register() function */
    header_field_info  hfinfo; /**< the field info to be registered */
} hf_register_info;

/** string representation, if one of the proto_tree_add_..._format() functions used */
typedef struct _item_label_t {
    char representation[ITEM_LABEL_LENGTH];
} item_label_t;

/** Contains the field information for the proto_item. */
typedef struct field_info {
    const header_field_info *hfinfo;      /**< pointer to registered field information */
    int                  start;           /**< current start of data in field_info.ds_tvb */
    int                  length;          /**< current data length of item in field_info.ds_tvb */
    int                  appendix_start;  /**< start of appendix data */
    int                  appendix_length; /**< length of appendix data */
    int                  tree_type;       /**< one of ETT_ or -1 */
    uint32_t             flags;           /**< bitfield like FI_GENERATED, ... */
    item_label_t        *rep;             /**< string for GUI tree */
    tvbuff_t            *ds_tvb;          /**< data source tvbuff */
    fvalue_t            *value;
    int                 total_layer_num;  /**< Hierarchical layer number, for all protocols in the tree. */
    int                 proto_layer_num;  /**< Protocol layer number, so 1st, 2nd, 3rd, ... for protocol X. */
} field_info;


/** One of these exists for the entire protocol tree. Each proto_node
 * in the protocol tree points to the same copy. */
typedef struct {
    GHashTable          *interesting_hfids;
    bool                 visible;
    bool                 fake_protocols;
    unsigned             count;
    packet_info         *pinfo;
} tree_data_t;

/** Each proto_tree, proto_item is one of these. */
typedef struct _proto_node {
    struct _proto_node *first_child;
    struct _proto_node *last_child;
    struct _proto_node *next;
    struct _proto_node *parent;
    field_info         *finfo;
    tree_data_t        *tree_data;
} proto_node;

/** A protocol tree element. */
typedef proto_node proto_tree;
/** A protocol item element. */
typedef proto_node proto_item;

struct _protocol {
	const char *name;               /* long description */
	const char *short_name;         /* short description */
	const char *filter_name;        /* name of this protocol in filters */
	GPtrArray  *fields;             /* fields for this protocol */
	int         proto_id;           /* field ID for this protocol */
	bool        is_enabled;         /* true if protocol is enabled */
	bool        enabled_by_default; /* true if protocol is enabled by default */
	bool        can_toggle;         /* true if is_enabled can be changed */
	int         parent_proto_id;    /* Used to identify "pino"s (Protocol In Name Only).
	                                   For dissectors that need a protocol name so they
	                                   can be added to a dissector table, but use the
	                                   parent_proto_id for things like enable/disable */
//	GList      *heur_list;          /* Heuristic dissectors associated with this protocol */
};
typedef struct _protocol protocol_t;

enum dissector_e {
	DISSECTOR_TYPE_SIMPLE,
	DISSECTOR_TYPE_CALLBACK
};
typedef int (*dissector_t)(tvbuff_t *, packet_info *, proto_tree *, void *);

/*
 * A dissector handle.
 */
struct dissector_handle {
	const char	*name;		/* dissector name */
	const char	*description;	/* dissector description */
	char            *pref_suffix;
	enum dissector_e dissector_type;
	union {
		dissector_t	dissector_type_simple;
//		dissector_cb_t	dissector_type_callback;
	} dissector_func;
	void		*dissector_data;
	protocol_t	*protocol;
};
